package com.googlecode.jsqlconverter.filter;

import com.googlecode.jsqlconverter.annotation.ParameterName;
import com.googlecode.jsqlconverter.annotation.ParameterOptional;
import com.googlecode.jsqlconverter.annotation.ServiceName;
import com.googlecode.jsqlconverter.definition.create.table.Column;
import com.googlecode.jsqlconverter.definition.create.table.CreateTable;
import com.googlecode.jsqlconverter.definition.type.ApproximateNumericType;
import com.googlecode.jsqlconverter.definition.type.BinaryType;
import com.googlecode.jsqlconverter.definition.type.BooleanType;
import com.googlecode.jsqlconverter.definition.type.DateTimeType;
import com.googlecode.jsqlconverter.definition.type.DecimalType;
import com.googlecode.jsqlconverter.definition.type.ExactNumericType;
import com.googlecode.jsqlconverter.definition.type.MonetaryType;
import com.googlecode.jsqlconverter.definition.type.NumericType;
import com.googlecode.jsqlconverter.definition.type.StringType;
import com.googlecode.jsqlconverter.definition.type.Type;
import com.googlecode.jsqlconverter.filter.interfaces.TransformTable;
import com.rits.cloning.Cloner;

@ServiceName("ReplaceTypeFilter")
public class ReplaceTypeFilter extends Filter implements TransformTable
{
	private Class<?>[] supportedTypes={ ApproximateNumericType.class, BinaryType.class, BooleanType.class,
			DateTimeType.class, ExactNumericType.class, MonetaryType.class, StringType.class};
	private Cloner cloner=new Cloner();
	
	private Type from;
	private Type to;
	private Integer sourceSize;
	private Integer targetSize;
	public ReplaceTypeFilter(
			@ParameterName("sourcetype") String source,
			@ParameterName("targettype") String target,
			@ParameterName("sourcesize") @ParameterOptional(defaultValue="null") Integer sourcesize,
			@ParameterName("targetsize") @ParameterOptional(defaultValue="null") Integer targetsize
			)
	{
		to=parseType(target);
		from=parseType(source);
		sourceSize=sourcesize;
		targetSize=targetsize;
	}


	private Type parseType(String value) {
		for (Class<?> en : supportedTypes) {
			Enum<?>[] enumList = (Enum<?>[]) en.getEnumConstants();

			for (Enum<?> myEnum : enumList) {
				if (value.equalsIgnoreCase(myEnum.toString())) {
					return (Type)myEnum;
				}
			}
		}
		return null;
	}


	private void convert(Column c) {
		if (c.getType()==from &&
				(sourceSize==null || sourceSize==c.getSize())) {
			c.setType(to);
			if (targetSize!=null) c.setSize(targetSize);
		}

	}
	
	@Override
	public CreateTable transform(CreateTable source) {
		CreateTable ret=cloner.deepClone(source);
		for (Column c : ret.getColumns())
			convert(c);
	
		return ret;
	}

}
